#pragma once

#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <memory>
#include "log.hpp"
#include "Mutex.hpp"
#include "Cond.hpp"
#include "Thread.hpp"


// namespace ThreadPoolModule
// {
//     using namespace LogMudule;
//     using namespace ThreadModule;
//     using namespace LockModule;
//     using namespace CondModule;

//     using thread_t = std::shared_ptr<Thread>;

//     template <typename T>
//     class ThreadPool
//     {
//     private: 
//         const static int defaultnum = 5; 
//         bool IsEmpty()
//         {
//             return _taskq.empty();
//         }
//         void HandlerTask(std::string name)
//         {
//             LOG(LogLevel::DEBUG)<<name<<"进入主逻辑";

//             //拿任务
//             while(true)
//             {
//                 T t;
//                 LockGuard l(_lock);

//                 while(IsEmpty() && _isrunning)
//                 {
//                     LOG(LogLevel::DEBUG)<<name<<"进入等待";
//                     _wait_num++;
//                     _cond.Wait(_lock);
//                     _wait_num--;
//                     LOG(LogLevel::DEBUG)<<name<<"完成等待";
//                 } 

//                 if(IsEmpty() && !_isrunning)
//                 {
//                     break;
//                 }

//                 t = _taskq.front();
//                 _taskq.pop();

//                  //执行任务
//                 t(name);
//             }
//         }

//         ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false)
//         {
//             for(int i = 0; i < _num; i++)
//             {
//                 _threads.push_back(std::make_shared<Thread>(std::bind(&ThreadPool::HandlerTask,this,std::placeholders::_1)));
//                 LOG(LogLevel::DEBUG)<<"对象"<<i<<"完成创建";
//             }
//         }

//         ThreadPool(const ThreadPool<T> & tp) = delete;
//         ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;

//     public:
//         static ThreadPool<T> *getInstance()
//         {
//             if(tp == nullptr)
//             {
//                 LockGuard l(_mutex);
//                 if(tp == nullptr)
//                 {
//                     tp = new ThreadPool<T>();
//                     LOG(LogLevel::DEBUG)<<"第一次完成创建";
//                 }
//             }

//             return tp;
//         }

        
//         void Equeue(T &&in)
//         {
//             if(_isrunning == false)
//                 return;

//             LockGuard l(_lock);
//             _taskq.push(std::move(in));
//             if(_wait_num > 0)
//             {
//                 _cond.Notify();
//                 LOG(LogLevel::DEBUG)<<"唤醒一个线程";
//             }
//         }
//         void Start()
//         {
//             if(_isrunning)
//                 return ;
            
//             _isrunning = true;
//             for(auto &e : _threads)
//             {
//                 e->Start();
//             }
//         }
//         void Wait()
//         {
//             for(auto &e : _threads)
//             {
//                 e->Join();
//             } 
//         }
//         void Stop()
//         {
//             LockGuard l(_lock);
//             if(_isrunning == false)
//                 return;

//             _isrunning = false;
//             if(_wait_num > 0)
//             {
//                 _cond.NotifyAll();
//             }
//         }
//         ~ThreadPool()
//         {}

//     private:
//         std::vector<thread_t> _threads; //线程组s
//         int _num;   //线程数量
//         int _wait_num;  //正在等待的线程数量
//         std::queue<T> _taskq; // 临界资源
//         Mutex _lock;    //锁
//         Cond _cond;     //条件变量
//         bool _isrunning;    //当前线程状态


//         static ThreadPool<T> *tp;   //线程池指针
//         static Mutex _mutex;    //为单例的锁
//     };

//     template <typename T>
//     ThreadPool<T>* ThreadPool<T>::tp = nullptr; 

//     template <typename T>
//     Mutex ThreadPool<T>::_mutex;
// }

namespace ThreadPoolModule
{
    //展开命名空间
    using namespace LogMudule;
    using namespace ThreadModule;
    using namespace LockModule;
    using namespace CondModule;

    //重命名
    using thread_t = std::shared_ptr<Thread>;

    //线程池类
    template <typename T>
    class ThreadPool
    {
    private: 
        const static int defaultnum = 5; //默认的线程数量 
        //注意：要加static，不然defaultnum需要实例化才生成，这会导致编译时失败

        //判断任务队列是否为空
        bool IsEmpty()
        {
            return _taskq.empty();
        }

        //线程同一执行的函数
        void HandlerTask(std::string name)
        {
            //日志
            LOG(LogLevel::DEBUG)<<name<<"进入主逻辑";

            //1.拿任务
            while(true)
            {
                T t;    //任务

                LockGuard l(_lock); //访问临界资源 - 加互斥锁


                //为空且为运行状态时才进行等待
                while(IsEmpty() && _isrunning)
                {
                    LOG(LogLevel::DEBUG)<<name<<"进入等待";
                    _wait_num++;
                    _cond.Wait(_lock);
                    _wait_num--;
                    LOG(LogLevel::DEBUG)<<name<<"完成等待";
                } 

                //走到这里只有任务队列不为空或者_isrunning == false -- 这种情况需要结束线程
                if(IsEmpty() && !_isrunning)
                {
                    break;
                }

                //2.取任务
                t = _taskq.front();
                _taskq.pop();

                 //3.执行任务
                t(name);
            }
        }

    public:
        
        //初始化成员变量
        ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false)
        {
            for(int i = 0; i < _num; i++)
            {
                //初始化线程池 - 此时还未正式创建线程
                _threads.push_back(std::make_shared<Thread>(std::bind(&ThreadPool::HandlerTask,this,std::placeholders::_1)));
                LOG(LogLevel::DEBUG)<<"对象"<<i<<"完成创建";
            }
        }

        //进入任务队列
        void Equeue(T &&in)
        {
            //线程池不在运行状态
            if(_isrunning == false)
                return;

            ////访问临界资源 - 加互斥锁
            LockGuard l(_lock);
            _taskq.push(std::move(in));

            //当有等待线程时需要唤醒
            if(_wait_num > 0)
            {
                _cond.Notify();
                LOG(LogLevel::DEBUG)<<"唤醒一个线程";
            }
        }

        //启动线程池 -- 正式创建线程
        void Start()
        {
            //已经是运行的状态了
            if(_isrunning)
                return ;

            //第一次设置为运行状态
            _isrunning = true;

            for(auto &e : _threads)
            {
                e->Start();
            }
        }

        //进程线程等待
        void Wait()
        {
            for(auto &e : _threads)
            {
                e->Join();
            } 
        }

        //暂停线程 
        void Stop()
        {
            ////访问临界资源 - 加互斥锁
            LockGuard l(_lock);
            if(_isrunning == false)
                return;

            //修改状态  -- 此时不能添加任务了
            _isrunning = false;

            //唤醒其他线程，再让其他线程将剩下的任务执行完了，最后再自己退出。
            if(_wait_num > 0)
            {
                _cond.NotifyAll();
            }
        }
        ~ThreadPool()
        {}

    private:
        std::vector<thread_t> _threads; //线程组s
        int _num;   //线程数量
        int _wait_num;  //正在等待的线程数量
        std::queue<T> _taskq; // 临界资源
        Mutex _lock;    //锁
        Cond _cond;     //条件变量
        bool _isrunning;    //当前线程状态
    };

}